package org.melanesia.beans;

import java.lang.reflect.Method;
import java.util.Map;

import org.melanesia.beans.exceptions.PropertyAccessException;

/**
 * Property setter using method access.
 *
 * @author marcin.kielar
 */
class MethodSetter implements Setter {

    /** Reflection method for accessing the property. */
    private final Method method;

    /**
     * Constructs new <code>MethodSetter</code> with method accessing the
     * property.
     *
     * @param method
     *            method accessing the property
     */
    MethodSetter(final Method method) {
        this.method = method;
    }

    @Override
    public void set(final Object bean, final Object value, final Map<String, Class<?>> intermediateBeanClasses) {

        try {

            Object acceptedValue = BeanUtils.cast(value, getAcceptedType());
            method.invoke(bean, acceptedValue);

        } catch (Throwable t) {
            throw new PropertyAccessException("Error mapping bean \"" + bean.getClass() + "\". Cannot set value by calling method \""
                    + method.getName() + "\" accepting type \"" + getAcceptedType() + "\" with parameter \"" + value + "\" of class \""
                    + (value == null ? "unknown" : value.getClass().getName()) + "\".", t);
        }
    }

    @Override
    public Class<?> getAcceptedType() {
        return method.getParameterTypes()[0];
    }
}
